home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i104: A Make for MS-DOS and VAX/VMS (msdos_mk)
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: ihnp4!killer!root
- Mod.sources: Volume 6, Issue 104
- Archive-name: msdos_mk
-
- [ This is so far different from the "standard" make, that it probably
- does not make sense to try to port it, although such a job looks
- to be fairly straightforward. Some of the ideas contained in this
- program might be interesting to other make fanciers besides myself.
- The manpage is, alas, "nroff output." --r$ ]
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # Contents: cmake.bat file.c macro.c make.bat make.c make.h make.man
- # makefile osdate.asm parsedir.c readme token.c
-
- echo x - cmake.bat
- sed 's/^XX//' > "cmake.bat" <<'@//E*O*F cmake.bat//'
- XXlc -ms -ie:\lc\ make
- XXlc -ms -ie:\lc\ macro
- XXlc -ms -ie:\lc\ token
- XXlc -ms -ie:\lc\ parsedir
- XXlc -ms -ie:\lc\ file
- XXmasm osdate;
- XXlink \lc\s\c make macro token parsedir file osdate,make,nul,\lc\s\lc
- @//E*O*F cmake.bat//
- chmod u=rw,g=r,o= cmake.bat
-
- echo x - file.c
- sed 's/^XX//' > "file.c" <<'@//E*O*F file.c//'
- XX#include <stdio.h>
- XX#include "make.h"
-
-
- XX/*
- XX * Return file-node for 'fname'.
- XX * If it doesn't exist, then create one.
- XX */
- XXFILENODE *filenode(fname)
- XXchar *fname;
- XX{
- XX FILENODE *f, *afnode(), *gfile();
-
- XX if((f = gfile(fname)) == NULL)
- XX f = afnode(fname);
- XX return f;
- XX}
-
-
- XX/*
- XX * Add a dependency to the node 'fnd'.
- XX * 'fnd' will depend on 'fname'.
- XX */
- XXaddfile(fnd, fname)
- XXFILENODE *fnd;
- XXchar *fname;
- XX{
- XX NODE *n;
- XX FILENODE *f;
-
- XX if(fnd == NULL) /* punt if no root file */
- XX {
- XX fprintf(stderr, "No current root, can't add dependency '%s'\n",
- XXfname);
- XX return;
- XX }
-
- XX f = filenode(fname);
- XX if((n = (NODE *)malloc(sizeof(NODE))) == NULL) allerr();
- XX n->nnext = fnd->fnode;
- XX fnd->fnode = n;
- XX n->nfile = f;
- XX}
-
-
- XX/*
- XX * Add a line of method-text to the node 'fnode'.
- XX */
- XXaddmeth(fnode, methtext)
- XXFILENODE *fnode;
- XXchar *methtext;
- XX{
- XX int len;
- XX char *new;
-
- XX if(fnode == NULL || methtext == NULL) return;
-
- XX len = strlen(methtext) + 2;
- XX if(fnode->fmake == NULL)
- XX {
- XX if((fnode->fmake = (char *)malloc(1)) == NULL) allerr();
- XX *(fnode->fmake) = 0;
- XX }
- XX len += strlen(fnode->fmake);
-
- XX/* Lattice C doesn't have 'realloc()', so this kludges around it: */
- XX if((new = (char *)malloc(len)) == NULL) allerr();
- XX strcpy(new, fnode->fmake);
- XX free(fnode->fmake);
- XX fnode->fmake = new;
-
- XX strcat(fnode->fmake, methtext);
- XX len = strlen(fnode->fmake);
- XX if(len && fnode->fmake[len - 1] != '\n')
- XX strcat(fnode->fmake, "\n");
- XX}
-
-
- XX/*
- XX * Get a filenode for the file called 'fn'.
- XX * Returns NULL if the node doesn't exist.
- XX */
- XXFILENODE *gfile(fn)
- XXchar *fn;
- XX{
- XX FILENODE *f;
-
- XX for(f = froot; f != NULL; f = f->fnext)
- XX if(!strcmp(fn, f->fname)) return f;
- XX return NULL;
- XX}
-
-
- XX/*
- XX * Alloc space for a new file node.
- XX */
- XXFILENODE *afnode(name)
- XXchar *name;
- XX{
- XX FILENODE *f;
-
- XX for(f=froot; f; f=f->fnext)
- XX if(!strcmp(name, f->fname)) return f;
-
- XX if((f = (FILENODE *)malloc(sizeof(FILENODE))) == NULL) allerr();
- XX if((f->fname = (char *)malloc(strlen(name)+1)) == NULL) allerr();
- XX strcpy(f->fname, name);
- XX f->fmake = NULL;
- XX f->fnode = NULL;
- XX f->fdate = NULL;
- XX f->fflag = 0;
-
- XX f->fnext = froot;
- XX froot = f;
- XX return f;
- XX}
-
-
- XX/*
- XX * Print dependency tree.
- XX */
- XXprtree()
- XX{
- XX FILENODE *f;
- XX NODE *n;
-
- XX for(f = froot; f != NULL; f = f->fnext)
- XX {
- XX printf("%s%s%s (%u, %u)\n",
- XX f->fname,
- XX (f->fflag & ROOTP) ? " (root)" : "",
- XX (f->fflag & REBUILT) ? " (rebuilt)" : "",
- XX (f->fdate != NULL) ? (f->fdate)->ds_high : 0,
- XX (f->fdate != NULL) ? (f->fdate)->ds_low : 0);
- XX if(f->fmake != NULL)
- XX printf("%s", f->fmake);
- XX for(n = f->fnode; n != NULL; n = n->nnext)
- XX printf("\t%s\n", (n->nfile)->fname);
- XX puts("");
- XX }
- XX}
- @//E*O*F file.c//
- chmod u=rw,g=r,o= file.c
-
- echo x - macro.c
- sed 's/^XX//' > "macro.c" <<'@//E*O*F macro.c//'
- XX#include <stdio.h>
- XX#include "make.h"
-
- XX/*
- XX * Macro processing
- XX */
-
-
- XX/*
- XX * Perform macro substitution from 'orig' to 'dest'.
- XX * Return number of macro substitutions made.
- XX * A macro reference is in one of two forms:
- XX * <MACCHAR>(macro-name)
- XX * or <MACCHAR><single-character>
- XX *
- XX * "<MACCHAR><MACCHAR>" expands to a single '<MACCHAR>'
- XX */
- XXmexpand(orig, dest, destsiz, macchar)
- XXchar *orig, *dest;
- XXint destsiz;
- XXchar macchar;
- XX{
- XX char *s, *d, mname[STRSIZ];
- XX int di, count;
- XX MACRO *m;
-
- XX di = count = 0;
- XX for(s=orig; *s;)
- XX if(*s == macchar)
- XX {
- XX if(*++s == macchar)
- XX {
- XX if(di < destsiz-1) dest[di++] = *s++;
- XX continue;
- XX }
-
- XX if(!*s) break;
- XX d = mname;
- XX if(*s != '(') *d++ = *s++;
- XX else
- XX {
- XX for(++s; *s && *s!=')';) *d++ = *s++;
- XX if(*s != ')') puts("Missed matching ')'");
- XX else ++s;
- XX }
- XX *d = 0;
- XX if((d = gmacro(mname)) == NULL)
- XX fprintf(stderr, "Undefined macro: %s\n", mname);
- XX else
- XX {
- XX while(*d && di < (destsiz - 1))
- XX dest[di++] = *d++;
- XX ++count;
- XX }
- XX } else if(di < destsiz-1)
- XX dest[di++] = *s++;
-
- XX dest[di]=0;
- XX return count;
- XX}
-
-
- XX/*
- XX * Define a macro.
- XX * Give the macro called 'name' the string expansion 'def'.
- XX * Old macro-names are superseded, NOT replaced.
- XX * Return ERROR if can't define the macro.
- XX */
- XXdefmac(name, def)
- XXchar *name, *def;
- XX{
- XX MACRO *m;
-
- XX if((m = (MACRO *)malloc(sizeof(MACRO))) == NULL) allerr();
- XX if((m->mname = (char *)malloc(strlen(name)+1)) == NULL) allerr();
- XX if((m->mvalue = (char *)malloc(strlen(def)+1)) == NULL) allerr();
-
- XX strcpy(m->mname, name);
- XX strcpy(m->mvalue, def);
- XX m->mnext = mroot;
- XX mroot = m;
- XX}
-
-
- XX/*
- XX * undefmac - undefine a macro.
- XX * Return 0 if macro was succesfully undefined, -1 if not found.
- XX */
- XXundefmac(name)
- XXchar *name;
- XX{
- XX MACRO *m = mroot;
- XX MACRO *prev = NULL;
-
- XX while(m != NULL && strcmp(name, m->mname))
- XX {
- XX prev = m;
- XX m = m->mnext;
- XX }
-
- XX if(m == NULL) return -1;
- XX if(prev == NULL) mroot = m->mnext;
- XX else prev->mnext = m->mnext;
-
- XX free(m->mname);
- XX free(m->mvalue);
- XX free(m);
- XX return 0;
- XX}
-
-
- XX/*
- XX * Lookup a macro called 'name'.
- XX * Return a pointer to its definition,
- XX * or NULL if it does not exist.
- XX */
- XXchar *gmacro(name)
- XXchar *name;
- XX{
- XX MACRO *m;
-
- XX for(m=mroot; m != NULL; m=m->mnext)
- XX if(!strcmp(name, m->mname)) return m->mvalue;
- XX return NULL;
- XX}
- @//E*O*F macro.c//
- chmod u=rw,g=r,o= macro.c
-
- echo x - make.bat
- sed 's/^XX//' > "make.bat" <<'@//E*O*F make.bat//'
- XXecho off
- XXif exist make$$$$.bat del make$$$$.bat
- XXxmake %1 %2 %3 %4 %5 %6 %7 %8 %9
- XXif exist make$$$$.bat make$$$$.bat
- @//E*O*F make.bat//
- chmod u=rw,g=r,o= make.bat
-
- echo x - make.c
- sed 's/^XX//' > "make.c" <<'@//E*O*F make.c//'
- XX#include <stdio.h>
- XX#include <ctype.h>
- XX#include "make.h"
-
- XX/*
- XX * MAKE - Maintain seperate source files
- XX *
- XX * SYNOPSIS
- XX * MK [-f file] [-a] [-n] [-d] [name] ...
- XX * f: use 'file' instead of default makefile
- XX * a: assume all modules are obsolete (recompile everything)
- XX * n: don't recompile, just list steps to recompile
- XX * d: debugging (print tree, file info)
- XX * name: module name to recompile
- XX *
- XX * 'secret' options (not to be used by humans):
- XX * -ofile 'file' is the script file to write to
- XX *
- XX * AUTHOR
- XX * Landon M. Dyer, Atari Inc.
- XX *
- XX */
-
- XX#define SCRIPTFILE "make$$$$.bat" /* (default) script-listing file */
- XX#define INIT "~INIT" /* initialization macro */
- XX#define DEINIT "~DEINIT" /* de-init macro */
- XX#define BEFORE "~BEFORE" /* the per-root 'startup' method */
- XX#define AFTER "~AFTER" /* the per-root 'wrapup' method */
-
-
- XXchar *mfiles[] = { /* default makefiles */
- XX "makefile",
-
- XX#ifdef VAXVMS
- XX "[-]makefile",
- XX "sys$login:makefile",
- XX#endif
-
- XX#ifdef MSDOS
- XX "..\makefile",
- XX#endif
- XX ""
- XX};
-
-
- XXMACRO *mroot = NULL; /* root of macro-list */
- XXFILENODE *froot = NULL; /* root of filenode-list */
- XXFILENODE *firstf = NULL; /* the very first filenode */
- XXFILE *mkfp = NULL; /* script file */
- XXchar *modnames[MAXMODS]; /* module-names mentioned in commandline */
- XXint modcount = 0; /* #of module-names */
- XXint debug = 0; /* nonzero: turn on debugging */
- XXint obsolete = 0; /* nonzero: every file should be recompiled */
- XXint noscript = 0; /* nonzero: print methods on standard output */
- XXchar *scriptf = SCRIPTFILE; /* default script file */
- XXDATE bigbang; /* a date, the very earliest possible */
- XXDATE endoftime; /* a date, the very last possible */
-
-
- XXmain(argc, argv)
- XXint argc;
- XXchar **argv;
- XX{
- XX int arg, i;
- XX char *mfile = NULL;
- XX DATE adate();
-
- XX bigbang = adate(0, 0); /* init root dates */
- XX endoftime = adate(~0, ~0);
-
- XX for(arg = 1; arg < argc; ++arg)
- XX if(*argv[arg] == '-') switch(tolower(argv[arg][1]))
- XX {
- XX case 'f':
- XX if(++arg >= argc)
- XX {
- XX fprintf(stderr, "-f needs filename argument.\n")
- XX;
- XX return;
- XX }
- XX mfile = argv[arg];
- XX break;
-
- XX case 'a':
- XX obsolete = 1;
- XX break;
-
- XX case 'n':
- XX noscript = 1;
- XX break;
-
- XX case 'd':
- XX debug = 1;
- XX break;
-
- XX case 'o':
- XX scriptf = argv[arg] + 2;
- XX break;
-
- XX default:
- XX fprintf(stderr, "Unknown switch: %c\n", argv[arg][1]);
- XX break;
- XX } else if(modcount < MAXMODS)
- XX modnames[modcount++] = argv[arg];
- XX else
- XX {
- XX fprintf(stderr, "Too many module names.\n");
- XX return;
- XX }
-
- XX if(mfile != NULL)
- XX {
- XX if(fmake(mfile) == -1)
- XX fprintf(stderr, "Cannot open makefile '%s'.\n", mfile);
- XX } else {
- XX for(i = 0; *mfiles[i]; ++i)
- XX if(fmake(mfiles[i]) != -1) break;
- XX if(!*mfiles[i])
- XX fprintf(stderr, "Cannot open makefile.\n");
- XX }
-
- XX if(debug) prtree();
- XX}
-
-
- XX/*
- XX * Construct dependency tree from the makefile 'fn'.
- XX * Figure out what has to be recompiled, and write a script file to do that.
- XX */
- XXfmake(fn)
- XXchar *fn;
- XX{
- XX FILE *fp;
-
- XX if((fp = fopen(fn, "r")) == NULL) return -1;
-
- XX fparse(fp);
- XX determ();
-
- XX fclose(fp);
- XX return 0;
- XX}
-
-
- XX/*
- XX * Parse the input file, defining macros and building the dependency tree.
- XX */
- XXfparse(fp)
- XXFILE *fp;
- XX{
- XX char ibuf[STRSIZ], ebuf[STRSIZ];
- XX char *strp, *tok1, *tok2, *s;
- XX FILENODE *lastf = NULL;
- XX FILENODE *sf;
-
- XX for(;;)
- XX {
- XX if(fgets(ibuf, STRSIZ, fp) == NULL) break;
- XX mexpand(ibuf, ebuf, STRSIZ, MACCHAR);
- XX escape(ebuf, COMCHAR);
-
- XX /* clobber last newline in string */
- XX s = ebuf + strlen(ebuf) - 1;
- XX if(s >= ebuf && *s == '\n') *s = '\0';
-
- XX if(*ebuf == '\t')
- XX {
- XX addmeth(lastf, ebuf+1);
- XX continue;
- XX }
-
- XX strp = ebuf;
- XX if((tok1 = token(&strp)) == NULL) continue;
- XX if((tok2 = token(&strp)) != NULL)
- XX if(!strcmp(tok2, DEFMAC))
- XX {
- XX if(*strp) defmac(tok1, strp);
- XX else if(undefmac(tok1) < 0)
- XX fprintf(stderr,
- XX "Can't undefine macro '%s'\n", tok1);
- XX continue;
- XX }
- XX else if(!strcmp(tok2, DEPEND))
- XX {
- XX addmeth(lastf, gmacro(AFTER));
-
- XX lastf = filenode(tok1);
- XX if(firstf == NULL) firstf = lastf;
- XX lastf->fmake = NULL;
-
- XX addmeth(lastf, gmacro(BEFORE));
-
- XX lastf->fflag |= ROOTP;
- XX while((tok1 = token(&strp)) != NULL)
- XX addfile(lastf, tok1);
- XX continue;
- XX }
- XX else addfile(lastf, tok2);
-
- XX do {
- XX addfile(lastf, tok1);
- XX } while((tok1 = token(&strp)) != NULL);
- XX }
-
- XX addmeth(lastf, gmacro(AFTER));
- XX}
-
-
- XX/*
- XX * Determine sequence of recompiles from the creation dates.
- XX * If there is anything to recompile, then create a script file full of commands
- XX.
- XX */
- XXdeterm()
- XX{
- XX FILENODE *f;
- XX int i;
- XX char *m;
-
- XX if(firstf == NULL) /* empty tree */
- XX {
- XX printf("No changes.\n");
- XX return;
- XX }
-
- XX if(modcount == 0) examine(firstf, endoftime);
- XX else for(i = 0; i < modcount; ++i)
- XX {
- XX if((f = gfile(modnames[i])) == NULL)
- XX {
- XX fprintf(stderr, "Can't find root '%s'.\n", modnames[i]);
- XX continue;
- XX }
-
- XX if(f->fflag & ROOTP == 0)
- XX {
- XX fprintf(stderr, "'%s' is not a root!\n", f->fname);
- XX continue;
- XX }
- XX examine(f, endoftime);
- XX }
-
- XX if(mkfp != NULL)
- XX {
- XX if((m = gmacro(DEINIT)) != NULL)
- XX {
- XX fputs(m, mkfp);
- XX fputc('\n', mkfp);
- XX }
- XX fclose(mkfp);
- XX } else printf("No changes.\n");
- XX}
-
-
- XX/*
- XX * Examine filenode 'fnd' and see if it has to be recompiled.
- XX * 'date' is the last-touched date of the node's father
- XX * (or 'endoftime' if its a root file.)
- XX * Root files with NO dependencies are assumed not to be up to date.
- XX */
- XXexamine(fnd, date)
- XXFILENODE *fnd;
- XXDATE date;
- XX{
- XX int rebuildp = 0;
- XX NODE *n;
-
- XX getdate(fnd);
- XX if(fnd->fnode == NULL && fnd->fflag & ROOTP)
- XX rebuildp = 1;
- XX else for(n = fnd->fnode; n != NULL; n = n->nnext)
- XX if(examine(n->nfile, fnd->fdate)) rebuildp = 1;
-
- XX if(rebuildp) recomp(fnd);
- XX if(obsolete || laterdt(fnd->fdate, date) >= 0)
- XX rebuildp = 1;
- XX return rebuildp;
- XX}
-
-
- XX/*
- XX * Make sure a filenode gets recompiled.
- XX */
- XXrecomp(f)
- XXFILENODE *f;
- XX{
- XX FILENODE *sf;
- XX char *m;
-
- XX if(mkfp == NULL)
- XX {
- XX if(noscript) mkfp = stdout;
- XX else if((mkfp = fopen(scriptf, "w")) == NULL)
- XX fprintf(stderr, "Cannot create: '%s'\n", scriptf);
-
- XX if((m = gmacro(INIT)) != NULL)
- XX {
- XX fputs(m, mkfp);
- XX fputc('\n', mkfp);
- XX }
- XX }
-
- XX if(f->fflag & REBUILT) return;
- XX if(f->fmake != NULL) fputs(f->fmake, mkfp);
- XX f->fflag |= REBUILT;
- XX}
-
-
- XX/*
- XX * Complain about being out of memory, and then die.
- XX */
- XXallerr() {
- XX fprintf(stderr, "Can't alloc -- no space left (I give up!)\n");
- XX exit(1);
- XX}
- @//E*O*F make.c//
- chmod u=rw,g=r,o= make.c
-
- echo x - make.h
- sed 's/^XX//' > "make.h" <<'@//E*O*F make.h//'
- XX/* #define VAXVMS 1 */ /* uncomment for VAX/VMS */
- XX/* #define MSDOS 1 */ /* uncomment for MSDOS */
-
- XX#ifdef VAXVMS
- XX#define ESCCHAR `\\` /* ok to use backslash on VMS */
- XX#endif
-
- XX#ifdef MSDOS
- XX#define ESCCHAR '`' /* since pathname char is backslash (yech) */
- XX#endif
-
- XX#define MACCHAR '#' /* macro-definition char */
- XX#define COMCHAR '!' /* comment char */
- XX#define DEFMAC "=" /* macro-definition token */
- XX#define DEPEND ":" /* dependency-definition token */
-
- XX#define DEBUG if(0)
- XX#define STRSIZ 512
- XX#define MAXMODS 50
-
- XX/* file attributes */
- XX#define REBUILT 0x01 /* file has been reconstructed */
- XX#define ROOTP 0x02 /* file was named on left side of DEPEND */
-
-
- XXstruct date_str {
- XX unsigned ds_low, ds_high;
- XX};
- XXtypedef struct date_str *DATE;
-
-
- XXstruct node {
- XX struct filenode *nfile; /* this node's file */
- XX struct node *nnext; /* the next node */
- XX};
- XXtypedef struct node NODE;
-
-
- XXstruct filenode {
- XX char *fname; /* the filename */
- XX char *fmake; /* remake string for file */
- XX DATE fdate; /* 32 bit last-modification date */
- XX NODE *fnode; /* files this file depends on */
- XX char fflag; /* magic flag bits */
- XX struct filenode *fnext; /* the next file */
- XX};
- XXtypedef struct filenode FILENODE;
-
-
- XXstruct macro {
- XX char *mname; /* the macro's name */
- XX char *mvalue; /* the macro's definition */
- XX struct macro *mnext; /* the next macro */
- XX};
- XXtypedef struct macro MACRO;
-
-
- XXextern MACRO *mroot;
- XXextern FILENODE *froot;
- XXextern DATE bigbang; /* Far, far in the past */
- XXextern DATE endoftime; /* Far, far in the future */
- XXchar *gmacro();
- XXFILENODE *filenode(), *gfile();
- XXchar *token();
- @//E*O*F make.h//
- chmod u=rw,g=r,o= make.h
-
- echo x - make.man
- sed 's/^XX//' > "make.man" <<'@//E*O*F make.man//'
- XXMAKE(I) 3/10/84 MAKE(I)
-
-
-
- XXNAME
- XX MAKE - maintain multiple source files (VAX/VMS and MSDOS 2.0)
-
-
- XXSYNOPSIS
- XX MAKE [-N] [-A] [-F makefile] [name ...]
-
-
- XXDESCRIPTION
- XX MAKE is a utility inspired by the Unix(tm) command of the same
- XX name. MAKE helps maintain programs that are constructed from
- XX many files. MAKE processes a "makefile", a file which describes
- XX how to build a program from its source files, and produces a
- XX script file containing the commands necessary to recompile the
- XX program.
-
- XX Be careful: this MAKE is NOT compatible with Unix(tm) MAKE!
-
- XX The 'N' option causes MAKE to print out the steps it would follow
- XX in order to rebuild the program. The 'A' option tells MAKE to
- XX assume that all files are obsolete, and that everything should be
- XX recompiled. The 'F' option, followed by a filename, can be used
- XX to specify a makefile other than the default one.
-
- XX If no names are specified in the commandline, the first dependency
- XX in the makefile is examined. Otherwise, the specified root names
- XX are brought up to date.
-
- XX The default makefiles are:
-
- XX for VAX/VMS: MAKEFILE
- XX [-]MAKEFILE
- XX SYS$LOGIN:MAKEFILE
-
- XX for MSDOS: MAKEFILE
- XX ..\MAKEFILE
-
- XX If the first makefile cannot be found, MAKE attempts to use the
- XX next one. If no makefile is ever found, MAKE prints a diagnostic
- XX and aborts.
-
-
-
-
-
- XXTHE MAKEFILE
- XX Comments begin with '!' and extend to the end of the line. A
- XX '!' (or almost any other character) may be escaped with the escape
- XX character (backslash (\) on VMS, backquote (`) on MSDOS). An escape
- XX character may be typed by doubling it (\\ or ``). The standard
- XX Unix escape codes are recognized (\n, \r, \t, \b, \f, `n, `r, `t,
- XX `b and `f).
-
- XX A makefile is a list of dependencies. A dependency consists of
- XX a root name, a colon, and zero or more names of dependent files.
- XX (The colon MUST be preceeded by whitespace.) For instance, in:
-
- XX make.exe : make.obj parsedir.obj file.obj macro.obj mk.h
-
- XX the file 'make.exe' depends on five other files. A root name
- XX with an empty dependency, as in:
-
- XX print :
-
- XX is assumed NEVER up to date, and will always be recompiled.
-
- XX The dependency list may be continued on successive lines:
-
- XX bigfile.exe : one.obj two.obj three.obj four.obj
- XX five.obj six.obj gronk.obj freeple.obj scuzzy.lnk
- XX frog.txt greeble.out
-
- XX Any number of 'method' lines may follow a dependency. Method lines
- XX begin with an ascii tab. When a file is to be recompiled, MAKE
- XX copies these method lines (minus the tab) to the script file.
- XX For example, in:
-
- XX make.exe : make.obj parsedir.obj file.obj macro.obj mk.h
- XX $link make, parsedir, file, macro
- XX $write sys$output "Just another version of MAKE ..."
- XX $purge
-
- XX the three lines following the dependency make up the method for
- XX recompiling (or in this case, re-linking) the file 'make.exe'.
-
- XX If the macro "~INIT" is defined, its text will appear first in the
- XX script file. If the macro "~DEINIT" is defined, its text will
- XX appear last in the script file. By defining these two macros, it
- XX is possible to configure the shell enviroment:
-
- XX ~INIT = $set term/nowrap\n$on error then goto err_handler
- XX ~DEINIT = $set term/wrap\n$exit\$err_handler:\n
- XX ~DEINIT = #(~DEINIT)$type err.log\n$exit
-
- XX will expand (in the script file) to:
-
- XX $set term/nowrap
- XX $on error then goto err_handler
- XX .
- XX .
- XX $set term/wrap
- XX $exit
- XX $err_handler:
- XX $type err.log
- XX $exit
-
- XX When a root's method is defined, the value of the macro "~BEFORE"
- XX is prefixed to the method, and the value of the macro "~AFTER" is
- XX appended to it.
-
- XX Frequently one wants to maintain more than one program with a single
- XX makefile. In this case, a "master dependency" can appear first in
- XX the file:
-
- XX allOfMyToolsAndHorribleHacks : cat peek poke.exe grunge
- XX cat : cat.exe
- XX cat.exe : ....
- XX (stuff for CAT.EXE)
- XX peek : peek.exe
- XX peek.exe : (stuff for PEEK.EXE)
- XX poke.exe : (stuff for POKE.EXE)
- XX grunge : grunge.com
- XX grunge.com : (stuff for grung)
-
- XX In other words, make will bring everything up to date that is somehow
- XX connected to the first dependency (its assumed that the incredibly
- XX lengthy filename specified in this example won't actually exist).
-
-
-
-
-
-
-
-
-
- XXMACROS
- XX A macro is defined by a line of the form (the '=' MUST be surrounded
- XX by whitespace):
-
- XX <macro-name> = <macro-body>
-
- XX A macro may be deleted by assigning an empty value to it. Macros
- XX may be redefined, but old definitions stay around. If a macro is
- XX redefined, and the redefinition is later deleted, the first definition
- XX will take effect:
-
- XX MAC = first ! MAC = "first"
- XX MAC = second ! MAC = "second"
- XX MAC = #(MAC) third ! MAC = "second third"
- XX MAC = ! MAC = "second"
- XX MAC = ! MAC = "first"
- XX MAC = ! MAC has no definition
-
- XX A macro may be referenced in two ways:
-
- XX #<char> or #(macro-name)
-
- XX The first way only works if the macro's name is a single character.
- XX If the macro's name is longer than one character, it must be
- XX enclosed in parenthesis. ['#' may be escaped by doubling it ("##".)]
- XX For example, in:
-
- XX G = mk.h mk1.h
- XX OBJS = make.obj file.obj parsedir.obj macro.obj
- XX BOTH = #(OBJS) #G
- XX
- XX make.exe : #(OBJS) #G
- XX make.exe : #(BOTH)
- XX make.exe : mk.h mk1.h make.obj file.obj parsedir.obj macro.obj
- XX $write sys$output "This is a number sign --> ##"
-
- XX after macro expansion, the three dependencies will appear identical
- XX and the two '#'s in the last line will turn into one '#'.
-
-
-
-
-
-
-
-
-
-
- XXUNIX(tm) MAKE AND THIS ONE
- XX They are NOT the same. Do not expect Unix makefiles to work with
- XX this MAKE, even if you change the pathnames. There are some major
- XX differences between this version and the standard Unix(tm) MAKE:
-
- XX 1. The Unix(tm) comment character is '#', VAX/VMS's is '!'.
-
- XX 2. The Unix(tm) macro-expansion character is '$'. While this would
- XX have been easy to leave the same, the '$' character is used so
- XX often in VAX/VMS command-lines that I thought it best to change
- XX it to '#'.
-
- XX 3. Multiple root names are not allowed. Unix(tm) MAKE accepts lines
- XX of the form:
-
- XX name1 name2 : depend1 depend2
-
- XX but this one doesn't.
-
- XX 4. There is no equivalent of double-colon ("::".)
-
- XX 5. There is no equivalent of .SUFFIXES, or the corresponding special
- XX macros.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- XXSAMPLE MAKEFILE
- XX !
- XX ! VAX/VMS MAKE
- XX ! Landon Dyer
- XX !
- XX H = make.h
- XX FILES = #H, make.c, macro.c, token.c, parsedir.c, file.c
- XX DOCUMENTATION = distr.mem make.man makefile. make.com
- XX
- XX make.exe : make.obj macro.obj token.obj parsedir.obj file.obj
- XX $link make.obj, macro, token, parsedir, file
- XX $purge
- XX
- XX make.obj : make.c #H
- XX $cc make.c
- XX
- XX macro.obj : macro.c #H
- XX $cc macro
- XX
- XX token.obj : token.c #H
- XX $cc token
- XX
- XX parsedir.obj : parsedir.c #H
- XX $cc parsedir
- XX
- XX file.obj : file.c
- XX $cc file
- XX
- XX !
- XX ! Print files associated with MAKE
- XX !
- XX print :
- XX $print make.man, #(FILES), make.com, makefile.
- XX
- XX !
- XX ! Type out source to MAKE
- XX !
- XX type :
- XX $type #(FILES), make.com, makefile.
- XX
- XX !
- XX ! Make backup of source files.
- XX !
- XX BACKUP = [.bak]
- XX backup :
- XX $copy #(FILES) #(BACKUP)
- XX $copy make.man, make.com, makefile. #(BACKUP)
- XX
- XX !
- XX ! Collect MAKE into a distribution file.
- XX !
- XX collect :
- XX $collect collect distr.mem make.man makefile make.com make.h -
- XX make.c macro.c token.c parsedir.c file.c
-
-
- XXAUTHOR
- XX Landon Dyer G.DYER@SU-SCORE.ARPA
- XX 175 Calvert Dr. #F-211 BASHFL::DYER (Atari Coinop)
- XX Cupertino, CA 95014
- @//E*O*F make.man//
- chmod u=rw,g=r,o= make.man
-
- echo x - makefile
- sed 's/^XX//' > "makefile" <<'@//E*O*F makefile//'
- XX!
- XX! MSDOS Make utility
- XX! (compile with Lattice C version 2.1)
- XX!
-
- XXCLIB = e:\lc\s\lc
- XXCOBJ = e:\lc\s\c
- XXLCS = lc -ms -ie:\lc\
- XXH = make.h
- XXFILES = #H make.c macro.c token.c parsedir.c file.c osdate.asm
- XXDOCUMENTATION = readme make.man makefile
-
- XXxmake.exe : make.obj macro.obj token.obj parsedir.obj file.obj osdate.obj
- XX link #(COBJ) make macro token parsedir file osdate,xmake,nul,#(CLIB)
-
- XXmake.obj : make.c #H
- XX #(LCS) make
-
- XXmacro.obj : macro.c #H
- XX #(LCS) macro
-
- XXtoken.obj : token.c #H
- XX #(LCS) token
-
- XXparsedir.obj : parsedir.c #H
- XX #(LCS) parsedir
-
- XXfile.obj : file.c
- XX #(LCS) file
-
- XXosdate.obj : osdate.asm
- XX masm osdate;
-
- XX!
- XX! Print files associated with MAKE
- XX!
- XXprint :
- XX print make.man #(FILES) makefile
-
-
- XX!
- XX! collect source and documentation files
- XX!
- XXcollect :
- XX collect -o make.col @make.lis
-
-
- XX!
- XX! copy to distribution disk (on A:)
- XX!
- XXdistribution :
- XX copy readme a:
- XX copy make.man a:
- XX copy makefile a:
- XX copy make.bat a:
- XX copy make.c a:
- XX copy macro.c a:
- XX copy token.c a:
- XX copy parsedir.c a:
- XX copy file.c a:
- XX copy osdate.asm a:
- XX copy cmake.bat a:
- XX copy make.lis a:
- XX copy xmake.exe a:
- @//E*O*F makefile//
- chmod u=rw,g=r,o= makefile
-
- echo x - osdate.asm
- sed 's/^XX//' > "osdate.asm" <<'@//E*O*F osdate.asm//'
- XXdos = 21h
-
- XXarg1 = 4 ; lattice argument indexes
- XXarg2 = arg1+2
- XXarg3 = arg2+2
-
- XXpgroup group prog
- XXprog segment byte public 'prog'
- XX public osdate
- XX assume cs:pgroup
-
- XX;
- XX;------
- XX; OSDATE - return file's creation-date (called from Lattice), or -1
- XX; if can't find the file.
- XX; Synopsis:
- XX; int osdate(filename, time1, time2)
- XX; char *filename;
- XX; int *time1, *time2;
- XX;
- XXosdate proc near
- XX push bp
- XX mov bp,sp
-
- XX;--- Open the file
- XX mov dx,[bp+arg1]
- XX xor al,al
- XX mov ah,3dh
- XX int dos
- XX jc osd$err ; can't, so complain
-
- XX;--- Get file's creation date and time
- XX mov bx,ax ; get handle's date info
- XX xor al,al
- XX mov ah,57h
- XX int dos
- XX jc osd$cls ; "can't happen" (but close it)
-
- XX;--- Install date/time info into caller's variables
- XX mov si,[bp+arg2] ; *arg2 = time (least significant)
- XX mov [si],cx
- XX mov si,[bp+arg3] ; *arg3 = date (most significant)
- XX mov [si],dx
-
- XX;--- Close file & return (ok)
- XX mov ah,3eh
- XX int dos
- XX xor ax,ax
- XX pop bp
- XX ret
-
- XX;--- Close file & return error condition
- XXosd$cls:
- XX mov ah,3eh
- XX int dos
- XXosd$err:
- XX mov ax,-1
- XX pop bp
- XX ret
- XXosdate endp
-
- XXprog ends
- XX end
- @//E*O*F osdate.asm//
- chmod u=rw,g=r,o= osdate.asm
-
- echo x - parsedir.c
- sed 's/^XX//' > "parsedir.c" <<'@//E*O*F parsedir.c//'
- XX#include <stdio.h>
- XX#include "make.h"
- XX#ifdef VAXVMS
- XX#include <rms.h>
- XX#endif
-
-
- XX/*
- XX * Get a file's creation date.
- XX */
- XXint getdate(f)
- XXFILENODE *f;
- XX{
- XX if(f->fdate != NULL || filedate(f) != -1) return;
-
- XX if(f->fflag & ROOTP == 0)
- XX {
- XX fprintf(stderr, "Can't get date for file '%s'\n", f->fname);
- XX f->fdate = endoftime;
- XX } else f->fdate = bigbang;
- XX return;
- XX}
-
-
- XX#ifdef VAXVMS
- XX/*
- XX * filedate - return file's creation date (VAX/VMS only.)
- XX * Returns -1 if file cannot be found, 0 if succesful.
- XX */
- XXfiledate(fnd)
- XXFILENODE *fnd;
- XX{
- XX unsigned *datetime;
- XX DATE adate();
- XX struct FAB *fptr;
- XX struct XABDAT *dptr;
-
- XX fptr = malloc(sizeof(struct FAB)); /* allocate FAB and XABDAT */
- XX dptr = malloc(sizeof(struct XABDAT));
- XX if(fptr == NULL || dptr == NULL) allerr();
- XX *fptr = cc$rms_fab; /* initialize FAB and XABDAT */
- XX *dptr = cc$rms_xabdat;
- XX fptr->fab$l_xab = (char *) dptr; /* FAB -> XABDAT */
-
- XX fptr->fab$l_fna = fnd->fname; /* setup filename */
- XX fptr->fab$b_fns = strlen(fnd->fname);
-
- XX if(sys$open(fptr) != RMS$_NORMAL || /* open the file */
- XX sys$display(fptr) != RMS$_NORMAL) /* get XABDAT info */
- XX return -1;
-
- XX datetime = &(dptr->xab$q_cdt); /* record 64-bit date */
- XX fnd->fdate = adate(datetime[0], datetime[1]);
-
- XX sys$close(fptr); /* close the file */
-
- XX free(dptr); /* clean up and return */
- XX free(fptr);
- XX return 0;
- XX}
- XX#endif
-
-
- XX#ifdef MSDOS
- XX/*
- XX * filedate - return file's creation date (MSDOS only.)
- XX * Returns -1 if file cannot be found, 0 if successful
- XX */
- XXfiledate(fnd)
- XXFILENODE *fnd;
- XX{
- XX unsigned date, time;
- XX DATE adate();
-
- XX if(osdate(fnd->fname, &time, &date) == -1) return -1;
- XX fnd->fdate = adate(time, date);
- XX}
- XX#endif
-
-
- XX/*
- XX * laterdt - compare two dates.
- XX * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
- XX */
- XXlaterdt(date1, date2)
- XXDATE date1, date2;
- XX{
- XX if(date1->ds_high > date2->ds_high ||
- XX (date1->ds_high >= date2->ds_high &&
- XX date1->ds_low > date2->ds_low)) return 1;
- XX else if(date1->ds_high == date2->ds_high &&
- XX date1->ds_low == date2->ds_low) return 0;
- XX else return -1;
- XX}
-
-
- XX/*
- XX * adate - allocate a date with the given time
- XX */
- XXDATE adate(time1, time2)
- XXunsigned time1, time2;
- XX{
- XX DATE d;
-
- XX if((d = (DATE)malloc(sizeof(struct date_str))) == NULL) allerr();
- XX d->ds_low = time1;
- XX d->ds_high = time2;
- XX return d;
-
- XX}
- @//E*O*F parsedir.c//
- chmod u=rw,g=r,o= parsedir.c
-
- echo x - readme
- sed 's/^XX//' > "readme" <<'@//E*O*F readme//'
-
- XXLast month I wrote a version of the Unix(tm) utility MAKE. It runs under
- XXVAX/VMS and MSDOS 2.0. I am placing it in the public domain, and it is yours
- XXfor the asking. You may copy it, or give it away. You can make any changes
- XXyou like to it. All I ask is that you DO NOT TRY TO SELL IT.
-
- XXAnyway, there is now a MAKE for MSDOS. It is free, and it works pretty well.
- XXI'm giving it away because it might do the world some good. Who knows?
-
- XXCaveat: this version of MAKE is NOT compatible with the Unix(tm) version.
- XXSome differences are explained in the documentation. Most of the problem stems
- XXfrom the fact that I've never had a chance to use the original version of MAKE,
- XXand the documentation I've seen on it has been poor. My idea of what a make
- XXprogram should do is almost certainly different from what you Unix(tm) hackers
- XXare used to. Well, hell -- the software is worth what you paid for it. Have
- XXfun.
-
- XXIn order to get MAKE running on your system, you need to:
-
- XX 1. Read the documentation file MAKE.MAN. (Yes, read the
- XX directions.)
-
- XX 2. Edit the file MAKE.H to represent your system (VAX/VMS or
- XX MSDOS 2.0.)
-
- XX 3. Recompile the source code by following the script file
- XX CMAKE.COM (for VAX/VMS) or CMAKE.BAT (for MSDOS 2.0.)
-
- XX VAX/VMS requires the DEC C compiler; MSDOS 2.0 requires
- XX Lattice C (or another C compiler of comparable quality)
- XX and the Macro Assembler.
-
- XX 4. Test out MAKE by running it on itself. (Make a backup
- XX first!)
-
-
-
- XX Good luck,
-
- XX Landon Dyer (G.DYER @ SU-SCORE)
- @//E*O*F readme//
- chmod u=rw,g=r,o= readme
-
- echo x - token.c
- sed 's/^XX//' > "token.c" <<'@//E*O*F token.c//'
- XX#include <stdio.h>
- XX#include <ctype.h>
- XX#include "make.h"
-
- XX/*
- XX * Get next token from the string. Return a pointer to it, or NULL.
- XX * Adjust pointer to point to next part of string.
- XX * The string is modified.
- XX * A token consists of any number of non-white characters.
- XX */
- XXchar *token(strpp)
- XXchar **strpp;
- XX{
- XX char *s, *beg;
-
- XX stripwh(strpp);
- XX if(!**strpp) return NULL;
-
- XX beg = s = *strpp;
- XX while(*s && !isspace(*s)) ++s;
- XX if(*s) *s++ = '\0';
- XX *strpp = s;
- XX return beg;
- XX}
-
-
- XX/*
- XX * Parse character escape-sequences in a line of text.
- XX * <EscChar><EscChar> = <EscChar>
- XX * <EscChar>n = newline, and so on
- XX * <EscChar><char> = <char>
- XX * The string is truncated at the first non-escaped occurance of 'comchar'.
- XX */
- XXescape(str, comchar)
- XXchar *str, comchar;
- XX{
- XX char *d, c;
-
- XX for(d = str; *str && *str != comchar; ++str)
- XX if(*str == ESCCHAR && *(str + 1)) switch((c = *++str))
- XX {
- XX case ESCCHAR:
- XX *d++ = ESCCHAR;
- XX break;
-
- XX case 'n':
- XX *d++ = '\n';
- XX break;
-
- XX case 'r':
- XX *d++ = '\r';
- XX break;
-
- XX case 't':
- XX *d++ = '\t';
- XX break;
-
- XX case 'b':
- XX *d++ = '\b';
- XX break;
-
- XX case 'f':
- XX *d++ = '\f';
- XX break;
-
- XX default:
- XX *d++ = c;
- XX break;
- XX } else *d++ = *str;
-
- XX *d++ = 0;
- XX}
-
-
- XXstripwh(strpp)
- XXchar **strpp;
- XX{
- XX char *s;
-
- XX s = *strpp;
- XX while(isspace(*s)) ++s;
- XX return (*strpp = s);
- XX}
- @//E*O*F token.c//
- chmod u=rw,g=r,o= token.c
-
- echo Inspecting for damage in transit...
- temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 7 30 193 cmake.bat
- 141 380 2556 file.c
- 125 341 2263 macro.c
- 4 21 116 make.bat
- 315 920 6271 make.c
- 64 263 1576 make.h
- 296 1146 7304 make.man
- 64 169 1070 makefile
- 63 180 1058 osdate.asm
- 110 336 2258 parsedir.c
- 40 272 1535 readme
- 83 211 1309 token.c
- 1312 4269 27509 total
- !!!
- wc cmake.bat file.c macro.c make.bat make.c make.h make.man makefile osdate.asm parsedir.c readme token.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if test -s $dtemp
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-
-
-
-